package cn.jinjimi.app.store.dao;

import android.content.ContentValues;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteStatement;

import cn.jinjimi.app.AccountManager;
import cn.jinjimi.app.custom.entity.Custom;
import cn.jinjimi.app.store.DaoSession;
import cn.jinjimi.app.store.DatabaseManager;
import cn.jinjimi.app.store.entity.custom.ContactInfo;
import cn.jinjimi.app.store.entity.custom.LastFollow;

import java.util.ArrayList;
import java.util.List;

import de.greenrobot.dao.AbstractDao;
import de.greenrobot.dao.Property;
import de.greenrobot.dao.internal.DaoConfig;
import de.greenrobot.dao.internal.SqlUtils;

/**
 * Created by Jinsen on 16/2/23.
 */
public class CustomerDao extends AbstractDao<Custom, Long> {
    public static final String TABLENAME = "CUSTOM";

    public static class Properties {

        public final static Property CustomerId = new Property(0, Long.class, "customerId", true, "CUSTOMER_ID");
        public final static Property Name = new Property(1, String.class, "name", false, "NAME");
        public final static Property Gender = new Property(2, Integer.class, "gender", false, "GENDER");
        public final static Property Avater = new Property(3, String.class, "avater", false, "AVATER");
        public final static Property SsoId = new Property(4, String.class, "ssoId", false, "SSO_ID");
        public final static Property BirthdayType = new Property(5, Integer.class, "birthdayType", false, "BIRTHDAY_TYPE");
        public final static Property Birthday = new Property(6, String.class, "birthday", false, "BIRTHDAY");
        public final static Property Type = new Property(7, Integer.class, "type", false, "TYPE");
        public final static Property Category = new Property(8, Integer.class, "category", false, "CATEGORY");
        public final static Property Label = new Property(9, String.class, "label", false, "LABEL");
        public final static Property Source = new Property(10, Integer.class, "source", false, "SOURCE");
        public final static Property SourceName = new Property(11, String.class, "sourceName", false, "SOURCE_NAME");
        public final static Property IdCard = new Property(12, Integer.class, "idCard", false, "ID_CARD");
        public final static Property IdCode = new Property(13, String.class, "idCode", false, "ID_CODE");
        public final static Property Email = new Property(14, String.class, "email", false, "EMAIL");
        public final static Property Province = new Property(15, String.class, "province", false, "PROVINCE");
        public final static Property City = new Property(16, String.class, "city", false, "CITY");
        public final static Property Top = new Property(17, Integer.class, "top", false, "TOP");
        public final static Property TopTime = new Property(18, Long.class, "topTime", false, "TOP_TIME");
        public final static Property PingyinName = new Property(19, String.class, "pingyinName", false, "PINGYIN_NAME");
        public final static Property FollowId = new Property(20, Long.class, "followId", false, "FOLLOW_ID");

    }

    private DaoSession daoSession;

    public CustomerDao(DaoConfig config) {
        super(config);
    }

    public CustomerDao(DaoConfig config, DaoSession daoSession) {
        super(config, daoSession);
        this.daoSession = daoSession;
    }

    public DaoSession returnDaoSession() {
        return daoSession;
    }

    /**
     * Creates the underlying database table.
     */
    public static void createTable(SQLiteDatabase db, boolean ifNotExists) {
        String constraint = ifNotExists ? "IF NOT EXISTS " : "";
        db.execSQL("CREATE TABLE " + constraint + "\"CUSTOM\" (" + //
                "\"CUSTOMER_ID\" INTEGER PRIMARY KEY ," + // 0: customerId
                "\"NAME\" TEXT," + // 1: name
                "\"GENDER\" INTEGER," + // 2: gender
                "\"AVATER\" TEXT," + // 3: avater
                "\"SSO_ID\" TEXT," + // 4: ssoId
                "\"BIRTHDAY_TYPE\" INTEGER," + // 5: birthdayType
                "\"BIRTHDAY\" TEXT," + // 6: birthday
                "\"TYPE\" INTEGER," + // 7: type
                "\"CATEGORY\" INTEGER," + // 8: category
                "\"LABEL\" TEXT," + // 9: label
                "\"SOURCE\" INTEGER," + // 10: source
                "\"SOURCE_NAME\" TEXT," + // 11: sourceName
                "\"ID_CARD\" INTEGER," + // 12: idCard
                "\"ID_CODE\" TEXT," + // 13: idCode
                "\"EMAIL\" TEXT," + // 14: email
                "\"PROVINCE\" TEXT," + // 15: province
                "\"CITY\" TEXT," + // 16: city
                "\"TOP\" INTEGER," + // 17: top
                "\"TOP_TIME\" INTEGER," + // 18: topTime
                "\"PINGYIN_NAME\" TEXT," + // 19: pingyinName
                "\"FOLLOW_ID\" INTEGER);"); // 20: followId
    }

    /**
     * Drops the underlying database table.
     */
    public static void dropTable(SQLiteDatabase db, boolean ifExists) {
        String sql = "DROP TABLE " + (ifExists ? "IF EXISTS " : "") + "\"CUSTOM\"";
        db.execSQL(sql);
    }

    /**
     * @inheritdoc
     */
    @Override
    protected void bindValues(SQLiteStatement stmt, Custom entity) {
        stmt.clearBindings();

        Long customerId = entity.customerId;
        if (customerId != null) {
            stmt.bindLong(1, customerId);
        }

        String name = entity.name;
        if (name != null) {
            stmt.bindString(2, name);
        }

        Integer gender = entity.gender;
        if (gender != null) {
            stmt.bindLong(3, gender);
        }

        String avatar = entity.avatar;
        if (avatar != null) {
            stmt.bindString(4, avatar);
        }

        String ssoId = entity.ssoId;
        if (ssoId != null) {
            stmt.bindString(5, ssoId);
        }

        Integer birthdayType = entity.birthdayType;
        if (birthdayType != null) {
            stmt.bindLong(6, birthdayType);
        }

        String birthday = entity.birthday;
        if (birthday != null) {
            stmt.bindString(7, birthday);
        }

        Integer type = entity.type;
        if (type != null) {
            stmt.bindLong(8, type);
        }

        Integer category = entity.category;
        if (category != null) {
            stmt.bindLong(9, category);
        }

        String label = entity.label;
        if (label != null) {
            stmt.bindString(10, label);
        }

        Integer source = entity.source;
        if (source != null) {
            stmt.bindLong(11, source);
        }

        String sourceName = entity.sourceName;
        if (sourceName != null) {
            stmt.bindString(12, sourceName);
        }

        Integer idCard = entity.idCard;
        if (idCard != null) {
            stmt.bindLong(13, idCard);
        }

        String idCode = entity.idCode;
        if (idCode != null) {
            stmt.bindString(14, idCode);
        }

        String email = entity.email;
        if (email != null) {
            stmt.bindString(15, email);
        }

        String province = entity.province;
        if (province != null) {
            stmt.bindString(16, province);
        }

        String city = entity.city;
        if (city != null) {
            stmt.bindString(17, city);
        }

        Integer top = entity.top;
        if (top != null) {
            stmt.bindLong(18, top);
        }

        Long topTime = entity.topTime;
        if (topTime != null) {
            stmt.bindLong(19, topTime);
        }

        Long followId = entity.followId;
        if (followId != null) {
            stmt.bindLong(21, followId);
        }
    }

    @Override
    protected void attachEntity(Custom entity) {
        super.attachEntity(entity);
        entity.__setDaoSession(daoSession);
    }

    /**
     * @inheritdoc
     */
    @Override
    public Long readKey(Cursor cursor, int offset) {
        return cursor.isNull(offset + 0) ? null : cursor.getLong(offset + 0);
    }

    /**
     * @inheritdoc
     */
    @Override
    public Custom readEntity(Cursor cursor, int offset) {
        Custom entity = new Custom( //
                cursor.isNull(offset + 0) ? null : cursor.getLong(offset + 0),     // customerId
                cursor.isNull(offset + 1) ? null : cursor.getString(offset + 1),   // name
                cursor.isNull(offset + 2) ? null : cursor.getInt(offset + 2),      // gender
                cursor.isNull(offset + 3) ? null : cursor.getString(offset + 3),   // avater
                cursor.isNull(offset + 4) ? null : cursor.getString(offset + 4),   // ssoId
                cursor.isNull(offset + 5) ? null : cursor.getInt(offset + 5),      // birthdayType
                cursor.isNull(offset + 6) ? null : cursor.getString(offset + 6),   // birthday
                cursor.isNull(offset + 7) ? null : cursor.getInt(offset + 7),      // type
                cursor.isNull(offset + 8) ? null : cursor.getInt(offset + 8),      // category
                cursor.isNull(offset + 9) ? null : cursor.getString(offset + 9),   // label
                cursor.isNull(offset + 10) ? null : cursor.getInt(offset + 10),    // source
                cursor.isNull(offset + 11) ? null : cursor.getString(offset + 11), // sourceName
                cursor.isNull(offset + 12) ? null : cursor.getInt(offset + 12),    // idCard
                cursor.isNull(offset + 13) ? null : cursor.getString(offset + 13), // idCode
                cursor.isNull(offset + 14) ? null : cursor.getString(offset + 14), // email
                cursor.isNull(offset + 15) ? null : cursor.getString(offset + 15), // province
                cursor.isNull(offset + 16) ? null : cursor.getString(offset + 16), // city
                cursor.isNull(offset + 17) ? null : cursor.getInt(offset + 17),    // top
                cursor.isNull(offset + 18) ? null : cursor.getLong(offset + 18),   // topTime
                cursor.isNull(offset + 19) ? null : cursor.getString(offset + 19), // pingyinName
                cursor.isNull(offset + 20) ? null : cursor.getLong(offset + 20)    // followId
        );
        return entity;
    }

    /**
     * @inheritdoc
     */
    @Override
    public void readEntity(Cursor cursor, Custom entity, int offset) {
        entity.customerId = (cursor.isNull(offset + 0) ? null : cursor.getLong(offset + 0));
        entity.name = (cursor.isNull(offset + 1) ? null : cursor.getString(offset + 1));
        entity.gender = (cursor.isNull(offset + 2) ? null : cursor.getInt(offset + 2));
        entity.avatar = (cursor.isNull(offset + 3) ? null : cursor.getString(offset + 3));
        entity.ssoId = (cursor.isNull(offset + 4) ? null : cursor.getString(offset + 4));
        entity.birthdayType = (cursor.isNull(offset + 5) ? null : cursor.getInt(offset + 5));
        entity.birthday = (cursor.isNull(offset + 6) ? null : cursor.getString(offset + 6));
        entity.type = (cursor.isNull(offset + 7) ? null : cursor.getInt(offset + 7));
        entity.category = (cursor.isNull(offset + 8) ? null : cursor.getInt(offset + 8));
        entity.label = (cursor.isNull(offset + 9) ? null : cursor.getString(offset + 9));
        entity.source = (cursor.isNull(offset + 10) ? null : cursor.getInt(offset + 10));
        entity.sourceName = (cursor.isNull(offset + 11) ? null : cursor.getString(offset + 11));
        entity.idCard = (cursor.isNull(offset + 12) ? null : cursor.getInt(offset + 12));
        entity.idCode = (cursor.isNull(offset + 13) ? null : cursor.getString(offset + 13));
        entity.email = (cursor.isNull(offset + 14) ? null : cursor.getString(offset + 14));
        entity.province = (cursor.isNull(offset + 15) ? null : cursor.getString(offset + 15));
        entity.city = (cursor.isNull(offset + 16) ? null : cursor.getString(offset + 16));
        entity.top = (cursor.isNull(offset + 17) ? null : cursor.getInt(offset + 17));
        entity.topTime = (cursor.isNull(offset + 18) ? null : cursor.getLong(offset + 18));
        entity.followId = (cursor.isNull(offset + 20) ? null : cursor.getLong(offset + 20));
    }

    /**
     * @inheritdoc
     */
    @Override
    protected Long updateKeyAfterInsert(Custom entity, long rowId) {
        entity.customerId = (rowId);
        return rowId;
    }

    /**
     * @inheritdoc
     */
    @Override
    public Long getKey(Custom entity) {
        if (entity != null) {
            return entity.customerId;
        } else {
            return null;
        }
    }

    /**
     * @inheritdoc
     */
    @Override
    protected boolean isEntityUpdateable() {
        return true;
    }

    private String selectDeep;

    protected String getSelectDeep() {
        if (selectDeep == null) {
            StringBuilder builder = new StringBuilder("SELECT ");
            SqlUtils.appendColumns(builder, "T", getAllColumns());
            builder.append(',');
            SqlUtils.appendColumns(builder, "T0", daoSession.getLastFollowDao().getAllColumns());
            builder.append(" FROM CUSTOM T");
            builder.append(" LEFT JOIN LAST_FOLLOW T0 ON T.\"FOLLOW_ID\"=T0.\"FOLLOW_ID\"");
            builder.append(' ');
            selectDeep = builder.toString();
        }
        return selectDeep;
    }

    protected Custom loadCurrentDeep(Cursor cursor, boolean lock) {
        Custom entity = loadCurrent(cursor, 0, lock);
        int offset = getAllColumns().length;

        LastFollow lastFollow = loadCurrentOther(daoSession.getLastFollowDao(), cursor, offset);
        entity.setLastFollow(lastFollow);

        return entity;
    }

    public Custom loadDeep(Long key) {
        assertSinglePk();
        if (key == null) {
            return null;
        }

        StringBuilder builder = new StringBuilder(getSelectDeep());
        builder.append("WHERE ");
        SqlUtils.appendColumnsEqValue(builder, "T", getPkColumns());
        String sql = builder.toString();

        String[] keyArray = new String[]{key.toString()};
        Cursor cursor = db.rawQuery(sql, keyArray);

        try {
            boolean available = cursor.moveToFirst();
            if (!available) {
                return null;
            } else if (!cursor.isLast()) {
                throw new IllegalStateException("Expected unique result, but count was " + cursor.getCount());
            }
            return loadCurrentDeep(cursor, true);
        } finally {
            cursor.close();
        }
    }

    /**
     * Reads all available rows from the given cursor and returns a list of new ImageTO objects.
     */
    public List<Custom> loadAllDeepFromCursor(Cursor cursor) {
        int count = cursor.getCount();
        List<Custom> list = new ArrayList<Custom>(count);

        if (cursor.moveToFirst()) {
            if (identityScope != null) {
                identityScope.lock();
                identityScope.reserveRoom(count);
            }
            try {
                do {
                    list.add(loadCurrentDeep(cursor, false));
                } while (cursor.moveToNext());
            } finally {
                if (identityScope != null) {
                    identityScope.unlock();
                }
            }
        }
        return list;
    }

    protected List<Custom> loadDeepAllAndCloseCursor(Cursor cursor) {
        try {
            return loadAllDeepFromCursor(cursor);
        } finally {
            cursor.close();
        }
    }


    /**
     * A raw-style query where you can pass any WHERE clause and arguments.
     */
    public List<Custom> queryDeep(String where, String... selectionArg) {
        Cursor cursor = db.rawQuery(getSelectDeep() + where, selectionArg);
        return loadDeepAllAndCloseCursor(cursor);
    }

    /* 获取客户最新最全数据 */
    public Custom loadDeepCustomById(Long customId) {
        daoSession.clear();
        Custom custom = loadDeep(customId);
        custom.resetContactInfos();
        custom.getContactInfos();
        return custom;
    }

    /* 查找当前用户的所有客户 */
    public List<Custom> queryBySsoid() {
        daoSession.clear();
        return queryBuilder().where(Properties.SsoId.eq(AccountManager.getInstance().getAccount().ssoid)).list();
    }

    /* 根据状态查询 */
    public List<Custom> queryByType(int type) {
        daoSession.clear();
        return queryBuilder().where(Properties.Type.eq(type))
                .where(Properties.SsoId.eq(AccountManager.getInstance().getAccount().ssoid))
                .list();
    }

    /**
     * 删除操作
     *
     * @param customId
     */
    public synchronized void delete(long customId) {
        DatabaseManager.getInstance().getLastFollowDao().clearLastFollowByCustomId(customId);
        DatabaseManager.getInstance().getContactInfoDao().clearContactInfoByCustomId(customId);

        deleteByKey(customId);
    }

    /**
     * 增加或更新一组客户数据
     *
     * @param customs
     */
    public synchronized void insertOrUpdate(List<Custom> customs) {
        for (Custom custom : customs) {
            insertOrUpdate(custom);
        }
    }

    public synchronized void insertOrUpdate(Custom custom) {
        custom.initPingyingName();

        if (custom.lastFollow != null) {
            DatabaseManager.getInstance().getLastFollowDao().clearLastFollowByCustomId(custom.customerId);
            custom.setLastFollow(custom.lastFollow);
            DatabaseManager.getInstance().getLastFollowDao().insertOrReplaceInTx(custom.lastFollow);
        }

        if (custom.contactInfos != null) {
            DatabaseManager.getInstance().getContactInfoDao().clearContactInfoByCustomId(custom.customerId);
            for (ContactInfo contactInfo : custom.contactInfos) {
                contactInfo.setSsoId(AccountManager.getInstance().getAccount().ssoid);
                contactInfo.setCustomerId(custom.customerId);
                DatabaseManager.getInstance().getContactInfoDao().insertOrReplaceInTx(contactInfo);
            }
        }

        if (queryBuilder().where(Properties.CustomerId.eq(custom.customerId)).count() > 0) {
            updateCustom(custom);// 不使用greenDao的默认插入是保证置顶以及置顶时间等本地数据得以缓存
        } else {
            insertOrReplaceInTx(custom);
        }
    }

    /**
     * 修改客户资料
     * 保存所有的客户资料,除了只保存在本地的数据
     *
     * @param custom
     */
    public synchronized void updateCustom(Custom custom) {
        Custom customOrogin = queryBuilder().where(Properties.CustomerId.eq(custom.customerId)).unique();
        if (customOrogin != null) {
            customOrogin.name = custom.name;
            customOrogin.gender = custom.gender;
            customOrogin.avatar = custom.avatar;
            customOrogin.birthday = custom.birthday;
            customOrogin.birthdayType = custom.birthdayType;
            customOrogin.type = custom.type;
            customOrogin.category = custom.category;
            customOrogin.label = custom.label;
            customOrogin.source = custom.source;
            customOrogin.sourceName = custom.sourceName;
            customOrogin.idCard = custom.idCard;
            customOrogin.idCode = custom.idCode;
            customOrogin.email = custom.email;
            customOrogin.province = custom.province;
            customOrogin.city = custom.city;
            customOrogin.followId = custom.followId;
            insertOrReplaceInTx(customOrogin);
        }
//        String where = Properties.CustomerId.columnName + " = ? ";
//        String[] whereValue = {Long.toString(custom.customerId)};
//
//        ContentValues cv = new ContentValues();
//        cv.put(Properties.CustomerId.columnName, custom.customerId);
//        cv.put(Properties.Name.columnName, custom.name);
//        cv.put(Properties.Gender.columnName, custom.gender);
//        cv.put(Properties.Avater.columnName, custom.avatar);
//        cv.put(Properties.SsoId.columnName, custom.ssoId);
//        cv.put(Properties.Birthday.columnName, custom.birthday);
//        cv.put(Properties.BirthdayType.columnName, custom.birthdayType);
//        cv.put(Properties.Type.columnName, custom.type);
//        cv.put(Properties.Category.columnName, custom.category);
//        cv.put(Properties.Label.columnName, custom.label);
//        cv.put(Properties.Source.columnName, custom.source);
//        cv.put(Properties.SourceName.columnName, custom.sourceName);
//        cv.put(Properties.IdCard.columnName, custom.idCard);
//        cv.put(Properties.IdCode.columnName, custom.idCode);
//        cv.put(Properties.Email.columnName, custom.email);
//        cv.put(Properties.Province.columnName, custom.province);
//        cv.put(Properties.City.columnName, custom.city);
//        cv.put(Properties.PingyinName.columnName, custom.getPingyinName());
//        cv.put(Properties.FollowId.columnName, custom.followId);
//        return db.update(TABLENAME, cv, where, whereValue);
    }

    /**
     * 修改用户置顶状态
     */
    public synchronized void updateTopState(long customId, int state, long time) {
        String where = Properties.CustomerId.columnName + " = ?";
        String[] whereValue = {Long.toString(customId)};
        ContentValues cv = new ContentValues();
        cv.put(Properties.Top.columnName, state);
        cv.put(Properties.TopTime.columnName, time);
        db.update(TABLENAME, cv, where, whereValue);
    }

}
